package com.mycat.dfs.server;

import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;

/**
 * FastDFS文件系统工具类
 *
 * @author roger.
 * @email 190642964@qq.com
 * @create 2017-02-06
 */
public class FastDFSUtil implements FastDFSService {

    /**
     * 配置文件地址
     */
    private String fdfsConfigPath;
    /**
     * 存储客户端对象
     */
    private StorageClient storageClient;

    private int connect_timeout;
    private String charset;
    private int network_timeout;
    private String secret_key;
    private int tracker_http_port;
    private boolean anti_steal_token;
    private String tracker_server_ip;
    private int tracker_server_port;

    public void init() throws FileNotFoundException, IOException, MyException {
        ClientGlobal.setG_connect_timeout(connect_timeout);
        ClientGlobal.setG_charset(charset);
        ClientGlobal.setG_network_timeout(network_timeout);
        ClientGlobal.setG_secret_key(secret_key);

        InetAddress addr = InetAddress.getByName(tracker_server_ip);
        InetSocketAddress tracker_servers = new InetSocketAddress(addr, tracker_server_port);
        InetSocketAddress[] tracker_servers_array = new InetSocketAddress[1];
        tracker_servers_array[0] = tracker_servers;

        ClientGlobal.setG_tracker_group(new TrackerGroup(tracker_servers_array));
        ClientGlobal.setG_tracker_http_port(tracker_http_port);
        ClientGlobal.setG_anti_steal_token(anti_steal_token);

        TrackerClient tracker = new TrackerClient();
        TrackerServer trackerServer = null;
        trackerServer = tracker.getConnection();
        StorageServer storageServer = null;
        storageClient = new StorageClient(trackerServer, storageServer);
    }

    /**
     * 通过绝对路径上传文件
     *
     * @param file 文件的绝对地址
     * @return FastDFS地址
     * @throws Exception
     */
    @Override
    public String uploadFile(String file) throws Exception {
        return this.uploadFile(file, null);
    }

    @Override
    public String uploadFileByByte(byte[] b, String fileExtName) throws Exception {
        try {
            this.init();
            String[] fileIds = storageClient.upload_file(b, fileExtName, null);
            if (fileIds != null) {
                return fileIds[0] + "/" + fileIds[1];
            } else {
                throw new Exception("FastDFS文件系统【上传】文件出现异常！！！！！！返回地址为空！！！！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【上传】文件出现异常！！！！！！！");
        }
    }

    @Override
    public String uploadFile(String file, NameValuePair[] metaList) throws Exception {
        try {
            this.init();
            String fileIds[] = storageClient.upload_file(file,
                    file.substring(file.lastIndexOf('.') + 1, file.length()), metaList);
            if (fileIds != null) {
                return fileIds[0] + "/" + fileIds[1];
            } else {
                throw new Exception("FastDFS文件系统【上传】文件出现异常！！！！！！返回地址为空！！！！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【上传】文件出现异常！！！！！！！");
        }
    }

    @Override
    public String uploadFile(InputStream is, String fileExtName, NameValuePair[] metaList) throws Exception {
        try {
            this.init();
            String[] fileIds = storageClient.upload_file(input2byte(is), fileExtName, metaList);
            if (fileIds != null) {
                return fileIds[0] + "/" + fileIds[1];
            } else {
                throw new Exception("FastDFS文件系统【上传】文件出现异常！！！！！！返回地址为空！！！！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【上传】文件出现异常！！！！！！！");
        }
    }

    @Override
    public String uploadFile(InputStream is, String fileExtName) throws Exception {
        return uploadFile(is, fileExtName, null);
    }

    @Override
    public byte[] downloadFile(String file) throws Exception {
        this.init();
        String groupName = file.substring(0, file.indexOf('/'));
        String filename = file.substring(file.indexOf('/') + 1, file.length());
        try {
            return storageClient.download_file(groupName, filename);
        } catch (IOException | MyException e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【下载】文件出现异常！！！！！！！");
        }
    }

    @Override
    public FileInfo getFileInfo(String file) throws Exception {
        this.init();
        String groupName = file.substring(0, file.indexOf('/'));
        String filename = file.substring(file.indexOf('/') + 1, file.length());
        try {
            return storageClient.get_file_info(groupName, filename);
        } catch (IOException | MyException e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【获取文件信息】出现异常！！！！！！！");
        }
    }

    @Override
    public NameValuePair[] getFileMeteInfo(String file) throws Exception {
        this.init();
        String groupName = file.substring(0, file.indexOf('/'));
        String filename = file.substring(file.indexOf('/') + 1, file.length());
        try {
            return storageClient.get_metadata(groupName, filename);
        } catch (IOException | MyException e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【获取文件内的数据】出现异常！！！！！！！");
        }
    }

    @Override
    public int deleteFile(String file) throws Exception {
        this.init();
        String groupName = file.substring(0, file.indexOf('/'));
        String filename = file.substring(file.indexOf('/') + 1, file.length());
        try {
            return storageClient.delete_file(groupName, filename);
        } catch (IOException | MyException e) {
            e.printStackTrace();
            throw new Exception("FastDFS文件系统【删除文件】出现异常！！！！！！！");
        }
    }

    /**
     * InputStream 转换为byte[]
     * @param inStream  InputStream
     * @return byte[]
     * @throws IOException
     */
    private static final byte[] input2byte(InputStream inStream) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }

    public void setFdfsConfigPath(String fdfsConfigPath) {
        this.fdfsConfigPath = fdfsConfigPath;
    }

    public void setStorageClient(StorageClient storageClient) {
        this.storageClient = storageClient;
    }

    public void setConnect_timeout(int connect_timeout) {
        this.connect_timeout = connect_timeout;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

    public void setNetwork_timeout(int network_timeout) {
        this.network_timeout = network_timeout;
    }

    public void setSecret_key(String secret_key) {
        this.secret_key = secret_key;
    }

    public void setTracker_http_port(int tracker_http_port) {
        this.tracker_http_port = tracker_http_port;
    }

    public void setAnti_steal_token(boolean anti_steal_token) {
        this.anti_steal_token = anti_steal_token;
    }

    public void setTracker_server_ip(String tracker_server_ip) {
        this.tracker_server_ip = tracker_server_ip;
    }

    public void setTracker_server_port(int tracker_server_port) {
        this.tracker_server_port = tracker_server_port;
    }
}
